package com.jmb.api.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jmb.api.web.core.http.ExecuteHandler;
import com.jmb.api.web.core.parser.Parser;
import com.jmb.api.common.exception.ValidUtilException;
import com.jmb.api.common.exception.WebApiException;
import com.jmb.api.common.result.ResultCodeEnum;
import com.jmb.api.common.utils.ValidUtil;
import com.jmb.api.entity.*;

import com.jmb.api.vo.Interface.Assert.InterfaceAssertVO;
import com.jmb.api.vo.Interface.Case.InterfaceCaseInfoVO;
import com.jmb.api.vo.Interface.Case.InterfaceCaseQueryVO;
import com.jmb.api.vo.Interface.Case.InterfaceCaseTO;
import com.jmb.api.vo.Interface.Case.Rely.InterfaceCaseRelyDataVO;
import com.jmb.api.vo.module.ModuleTO;
import com.jmb.api.vo.rely.RelyDataVO;
import com.jmb.api.web.mapper.*;
import com.jmb.api.web.service.InterfaceAssertService;
import com.jmb.api.web.service.InterfaceCaseService;
import com.jmb.api.web.service.InterfacePreCaseService;
import com.jmb.api.web.service.InterfaceProcessorService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
* @author 金梦博
* @description 针对表【t_interface_case】的数据库操作Service实现
* @createDate 2025-09-25 17:18:52
*/
@Slf4j
@Service
public class InterfaceCaseServiceImpl extends ServiceImpl<InterfaceCaseMapper, InterfaceCase>
    implements InterfaceCaseService {

    @Autowired
    private InterfaceCaseMapper interfaceCaseMapper;
    @Autowired
    private ModuleMapper moduleMapper;
    @Autowired
    private InterfacePreCaseService preCaseService;
    @Autowired
    private InterfaceAssertService assertService;
    @Autowired
    private InterfaceProcessorService processorService;
    @Autowired
    private Parser parser;
    @Autowired
    private InterfaceCaseRelyDataMapper interfaceCaseRelyDataMapper;
    @Autowired
    private RelyDataMapper relyDataMapper;
   @Autowired
   private InterfaceAssertMapper interfaceAssertMapper;
   @Autowired
   private ExecuteHandler executeHandler;





    /**
     * 新增接口测试用例
     * @param interfaceCase 测试用例
     */

    @Override
    public InterfaceCase saveInterfaceCase(InterfaceCase interfaceCase) {
        Long moduleId = interfaceCase.getModuleId();
        long projectId = interfaceCase.getProjectId();
        Integer bodyType = interfaceCase.getBodyType();
        if (bodyType>=3 && bodyType!=9){
            throw new WebApiException(ResultCodeEnum.BODY_TYPE_ERROR);
        }
        ModuleTO moduleTO = new ModuleTO();
        moduleTO.setModuleId(moduleId);
        moduleTO.setProjectId(projectId);
        if (moduleMapper.selectModuleList(moduleTO).isEmpty()){
            log.info("新增接口测试用例，模块编号/项目编号不存在");
            throw new WebApiException(ResultCodeEnum.MODULE_NOT_EXIST);
        }
        this.save(interfaceCase);
        return interfaceCase;
    }

    @Override
    public void saveInterfaceCaseAndAssertAndPostProcessorAndPreCase(InterfaceCaseTO interfaceCase) {
        // 插入用例，获取编号
        Long caseId = this.saveInterfaceCase(interfaceCase).getId();
        // 插入前置用例
        List<InterfacePreCase> preCases = interfaceCase.getPreCases();
        if (!CollectionUtils.isEmpty(preCases)){
            for (InterfacePreCase preCase : preCases){
                Long preCaseId = interfaceCase.getId();
                ValidUtil.notNUll(this.findInterfaceCaseById(preCaseId), "前置用例编号不存在");
                if (interfaceCase.getId().equals(caseId)){
                    log.error("保存前置用例，前置用例编号不能为自身");
                    throw new WebApiException(ResultCodeEnum.PRE_CASE_NOT_SELF);
                }
                preCase.setParentCaseId(caseId);
                preCaseService.saveOrUpdateInterfacePreCase(preCase);
            }
        }
        // 插入断言表
        List<InterfaceAssert> assertList = interfaceCase.getAsserts();
        if (!CollectionUtils.isEmpty(assertList)){
            for (InterfaceAssert anAssert : assertList){
                anAssert.setCaseId(caseId);
                assertService.saveAssert(anAssert);

            }
        }
        // 插入处理器表
        List<InterfaceProcessor> processorList = interfaceCase.getPostProcessors();
        if (!CollectionUtils.isEmpty(processorList)){
            for (InterfaceProcessor processor : processorList){
                processor.setCaseId(caseId);
                processorService.saveOrUpdateInterfaceProcessor(processor);
            }
        }

    }

    // 查询接口测试用例详情
    @Override
    public InterfaceCaseInfoVO findInterfaceCaseById(Long id) {
        return interfaceCaseMapper.selectInterfaceCaseByCaseId(id);
    }

    /**
     * 修改测试用例
     * @param interfaceCase 测试用例
     */
    @Override
    public void modifyInterfaceCase(InterfaceCaseTO interfaceCase) {
        // 获取caseId
        Long caseId = interfaceCase.getId();
        // 获取bodyType
        Integer bodyType = interfaceCase.getBodyType();
        // 判断bodyType
        if (bodyType>=3 && bodyType!=9){
            throw new WebApiException(ResultCodeEnum.BODY_TYPE_ERROR);
        }
        InterfaceCase faceCase = new InterfaceCase();
        BeanUtils.copyProperties(interfaceCase,faceCase);
        // 检查属性中的接口依赖是否包含自身
        this.checkDependencyInCaseProperty(caseId, interfaceCase.getHeaders(), "请求头", false);
        this.checkDependencyInCaseProperty(caseId, interfaceCase.getParams(), "请求参数", false);
        this.checkDependencyInCaseProperty(caseId, interfaceCase.getFormData(), "formData", false);
        this.checkDependencyInCaseProperty(caseId, interfaceCase.getFormDataEncoded(), "formDataEncoded", false);
        this.checkDependencyInCaseProperty(caseId, interfaceCase.getRaw(), "raw", false);


        Long moduleId = interfaceCase.getModuleId();
        long projectId = interfaceCase.getProjectId();
        ModuleTO moduleTO = new ModuleTO();
        moduleTO.setModuleId(moduleId);
        moduleTO.setProjectId(projectId);
        // 判断入参，ModuleId是否存在，projectId是否存在
        if (moduleMapper.selectModuleList(moduleTO).isEmpty()){
            log.info("修改接口测试用例，模块编号/项目编号不存在");
            throw new WebApiException(ResultCodeEnum.MODULE_NOT_EXIST);
        }
        interfaceCaseMapper.updateById(faceCase);
        // 处理断言
        List<InterfaceAssert> assertList = interfaceCase.getAsserts();
        List<Long> assertIds = interfaceAssertMapper.selectAllAssertIds(interfaceCase.getId());
        if (!CollectionUtils.isEmpty(assertList)){
            for (InterfaceAssert anAssert : assertList){
                // 检查断言预期结果中依赖是否包含自身
                String exceptedResult = anAssert.getExceptedResult();
                this.checkDependencyInCaseProperty(caseId, exceptedResult, "断言预期结果", false);
                // 修改断言表，修改存在的数据
                anAssert.setCaseId(interfaceCase.getId());
                assertService.saveAssert(anAssert);
                // 判断一下是否传case Id
                if (anAssert.getId() == null){
                    assertService.saveAssert(anAssert);
                }else {
                    // 如果存在移除此前新增的id队列
                    for (int i = assertIds.size() - 1; i >= 0; i--) {
                        if (assertIds.get(i).equals(anAssert.getId())){
                            assertIds.remove(i);
                        }

                    }
                }
            }
            for (Long assertId : assertIds){
                assertService.removeById(assertId);
            }
        }else {
            // 删除所有断言
            LambdaQueryWrapper<InterfaceAssert> assertLambdaQueryWrapper = new LambdaQueryWrapper<>();
            assertLambdaQueryWrapper.eq(InterfaceAssert::getCaseId, caseId);
            assertService.remove(assertLambdaQueryWrapper);
        }
        // 处理前置用例
        List<InterfacePreCase> preCases = interfaceCase.getPreCases();
        // 获取所有前置用例编号
        List<Long> preIdList = preCaseService.findInterfacePreIdByParentId(interfaceCase.getId());
        // 删除所有前置用例
        if (!CollectionUtils.isEmpty(preCases)){
            for (InterfacePreCase preCase : preCases){
                InterfaceCaseInfoVO preCaseVO = this.findInterfaceCaseById(preCase.getPreCaseId());
                ValidUtil.notNUll(preCaseVO, "前置用例编号不存在");
                List<InterfaceAssertVO> preCaseVOAsserts = preCaseVO.getAsserts();
                // 前置用例不能为自身
                this.checkDependencyInCaseProperty(caseId, preCaseVO.getHeaders(), "请求头"+interfaceCase.getId(), true);
                this.checkDependencyInCaseProperty(caseId, preCaseVO.getParams(), "请求参数"+interfaceCase.getId(), true);
                this.checkDependencyInCaseProperty(caseId, preCaseVO.getFormData(), "formData"+interfaceCase.getId(), true);
                this.checkDependencyInCaseProperty(caseId, preCaseVO.getFormDataEncoded(), "formDataEncoded"+interfaceCase.getId(), true);
                this.checkDependencyInCaseProperty(caseId, preCaseVO.getRaw(), "raw"+interfaceCase.getId(), true);
                for (InterfaceAssertVO preCaseVOAssert : preCaseVOAsserts) {
                    String exceptedResult = preCaseVOAssert.getExceptedResult();
                    this.checkDependencyInCaseProperty(caseId, exceptedResult, "断言预期结果"+interfaceCase.getId(), true);
                }
                interfaceCase.setId(interfaceCase.getId());
                // 修改已存在的数据
                preCaseService.saveOrUpdateInterfacePreCase(preCase);
                // 判断一下是否传case Id
                if (preCase.getId() == null){
                    preCaseService.saveOrUpdateInterfacePreCase(preCase);
                }else {
                    // 如果存在移除此前新增的id队列
                    for (int i = preIdList.size() - 1; i >= 0; i--) {
                        if (preIdList.get(i).equals(preCase.getId())){
                            preIdList.remove(i);
                        }

                    }
                }
            }for (Long preId : preIdList){
                preCaseService.removeById(preId);
            }
        }else {
            // 移除该用例下所有的前置用例
            LambdaQueryWrapper<InterfacePreCase> preCaseQuery = new LambdaQueryWrapper<>();
            preCaseQuery.eq(InterfacePreCase::getParentCaseId, interfaceCase.getId());
            preCaseService.remove(preCaseQuery);
        }
        // 修改处理器
        List<InterfaceProcessor> postProcessors = interfaceCase.getPostProcessors();
        List<Long> postProcessorIdList = processorService.findInterfaceProcessorIdByCaseId(interfaceCase.getId());
        if (!CollectionUtils.isEmpty(postProcessors)){
            for (InterfaceProcessor processor : postProcessors){
                processor.setCaseId(interfaceCase.getId());
                // 修改已存在数据
                processorService.saveOrUpdateInterfaceProcessor(processor);
                // 移除此次新增钱的id队列
                for (int i = postProcessorIdList.size() - 1; i >= 0; i--){
                    if (postProcessorIdList.get(i).equals(processor.getId())){
                        postProcessorIdList.remove(i);
                    }
                }
            }
            for (Long postProcessorId : postProcessorIdList){
                processorService.removeById(postProcessorId);
            }
        }else {
            // 移除该用例下的所有处理器
            LambdaQueryWrapper<InterfaceProcessor> processorQuery = new LambdaQueryWrapper<>();
            processorQuery.eq(InterfaceProcessor::getCaseId, interfaceCase.getId());
            processorService.remove(processorQuery);
        }


    }

    @Override
    public IPage<InterfaceCaseQueryVO> listInterfaceCase(IPage<InterfaceCaseQueryVO> page, InterfaceCaseQueryVO interfaceCase) {
        return interfaceCaseMapper.selectInterfaceCaseList(page, interfaceCase);
    }

    @Override
    public Long executeInterfaceCase(ExecuteInterfaceCaseParam caseParam) {
        return executeHandler.executeInterfaceCase(caseParam);
    }


    /**
     * 检查属性中的接口依赖是否包含自身
     * @param caseId 用例编号
     * @param propertyName 域，如headers、params、formdata、formdataencoded、raw
     * @param propertyDesc 描述
     * @param isPreCase 是否为前置用例
     */
    private void checkDependencyInCaseProperty(Long caseId, String propertyName, String propertyDesc,boolean isPreCase){
        ArrayList<String> dependencyNames = parser.extractTextName(propertyName);
        if (dependencyNames ==  null){
            return;
        }
        for (String dependencyName : dependencyNames){
            // 检查接口依赖
            InterfaceCaseRelyDataVO caseRelyDataVO = interfaceCaseRelyDataMapper.selectIfRelyDataByName(dependencyName);
            if (caseRelyDataVO != null){
                Long relyCaseId = caseRelyDataVO.getRelyCaseId();
                if (relyCaseId.equals(caseId)){
                    log.error("保存接口依赖，依赖用例编号不能为自身");
                    throwSelfReferenceException(propertyDesc, isPreCase, propertyName);
                }
            }
            // 检查SQL依赖中的接口依赖
            RelyDataVO relyDataVO = relyDataMapper.selectRelyDataByName(dependencyName);
            if (relyDataVO != null && relyDataVO.getType()!=null && relyDataVO.getType()>1){
                String sql = relyDataVO.getValue();
                ArrayList<String> sqlDependencies = parser.extractTextName(sql);
                if (sqlDependencies ==null){
                    continue;
                }
                for (String sqlDependency : sqlDependencies){
                    InterfaceCaseRelyDataVO relyDataByNameSql = interfaceCaseRelyDataMapper.selectIfRelyDataByName(sqlDependency);
                    if (relyDataByNameSql != null){
                        Long relyCaseId = relyDataByNameSql.getRelyCaseId();
                        if (relyCaseId.equals(caseId)){
                            log.error("保存接口依赖，依赖用例编号不能为自身,SQL");
                            throwSelfReferenceException(propertyDesc, isPreCase, propertyName);
                        }
                    }
                }
            }

        }


    }

    /**
     * 统一抛出自引用异常的方法
     */
    private void throwSelfReferenceException(String propertyDesc, boolean isPreCase, String prefix)  {
        String template = isPreCase
                ? "当前用例的前置用例%s中的" + prefix + "依赖不能引用自身"
                : "当前用例%s中的" + prefix + "依赖不能引用自身";
        throw new ValidUtilException(String.format(template, propertyDesc));
    }


}




